#include <syscall.h>
#include <stdint.h>

static const long IGNORE = 0L;

static long invoke_syscall(long sysno, long arg0, long arg1, long arg2,
                           long arg3, long arg4)
{
    /* TODO: [p2-task3] implement invoke_syscall via inline assembly */
    asm volatile("nop");
    register unsigned long a0 asm ("a0") = (unsigned long)(arg0);   
    register unsigned long a1 asm ("a1") = (unsigned long)(arg1);   
    register unsigned long a2 asm ("a2") = (unsigned long)(arg2);   
    register unsigned long a3 asm ("a3") = (unsigned long)(arg3);   
    register unsigned long a4 asm ("a4") = (unsigned long)(arg4);   
    register unsigned long a7 asm ("a7") = (unsigned long)(sysno);
    asm volatile ("ecall"                   
              : "+r" (a0)               
              : "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a7)        
              : "memory");
    return a0;
}

void sys_yield(void)
{
    /* TODO: [p2-task3] call invoke_syscall to implement sys_yield */
    invoke_syscall(SYSCALL_YIELD,0,0,0,0,0);
}

void sys_move_cursor(int x, int y)
{
    /* TODO: [p2-task3] call invoke_syscall to implement sys_move_cursor */
    invoke_syscall(SYSCALL_CURSOR,(long)x,(long)y,0,0,0);
}

void sys_write(char *buff)
{
    /* TODO: [p2-task3] call invoke_syscall to implement sys_write */
    invoke_syscall(SYSCALL_WRITE,(long)buff,0,0,0,0);
}

void sys_reflush(void)
{
    /* TODO: [p2-task3] call invoke_syscall to implement sys_reflush */
    invoke_syscall(SYSCALL_REFLUSH,0,0,0,0,0);
}

int sys_mutex_init(int key)
{
    /* TODO: [p2-task3] call invoke_syscall to implement sys_mutex_init */
    invoke_syscall(SYSCALL_LOCK_INIT,(long)key,0,0,0,0);
    return 0;
}

void sys_mutex_acquire(int mutex_idx)
{
    /* TODO: [p2-task3] call invoke_syscall to implement sys_mutex_acquire */
    invoke_syscall(SYSCALL_LOCK_ACQ,(long)mutex_idx,0,0,0,0);
}

void sys_mutex_release(int mutex_idx)
{
    /* TODO: [p2-task3] call invoke_syscall to implement sys_mutex_release */
    invoke_syscall(SYSCALL_LOCK_RELEASE,(long)mutex_idx,0,0,0,0);
}

long sys_get_timebase(void)
{
    /* TODO: [p2-task3] call invoke_syscall to implement sys_get_timebase */
    return  invoke_syscall(SYSCALL_GET_TIMEBASE,0,0,0,0,0);;
}

long sys_get_tick(void)
{
    /* TODO: [p2-task3] call invoke_syscall to implement sys_get_tick */
    return invoke_syscall(SYSCALL_GET_TICK,0,0,0,0,0);;
}

void sys_sleep(uint32_t time)
{
    /* TODO: [p2-task3] call invoke_syscall to implement sys_sleep */
    invoke_syscall(SYSCALL_SLEEP,(long)time,0,0,0,0);
}

void sys_thread_create(ptr_t func, int pid)
{
    invoke_syscall(SYSCALL_THREAD_CREATE,func,pid,0,0,0);
}